package top.oneit.jdownload.download;

import cn.hutool.core.io.IoUtil;
import lombok.extern.slf4j.Slf4j;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import top.oneit.jdownload.config.AddChrome95RequestHeadersInterceptor;
import top.oneit.jdownload.constants.JConstants;
import top.oneit.jdownload.controller.item.ActionsItemController;
import top.oneit.jdownload.data.dao.DownloadSaveStatusDao;
import top.oneit.jdownload.data.entity.DownloadFile;
import top.oneit.jdownload.data.entity.DownloadSaveStatus;
import top.oneit.jdownload.utils.HttpUtils;

import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @author lingkang
 * @date 2021/11/21
 */
@Slf4j
public class DownloadingTask implements Runnable {
    private DownloadSaveStatus downloadSaveStatus;
    private ActionsItemController controller;

    public DownloadingTask(DownloadSaveStatus downloadSaveStatus, ActionsItemController controller) {
        this.downloadSaveStatus = downloadSaveStatus;
        this.controller = controller;
    }

    @Override
    public void run() {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(20, TimeUnit.SECONDS) //连接超时
                .addInterceptor(new AddChrome95RequestHeadersInterceptor())
                .build();

        DownloadFile downloadFile = downloadSaveStatus.getDownloadingTablePo().getDownloadFile();
        Map<String, String> head = new HashMap<>();
        head.put("Range", "bytes=" + downloadSaveStatus.getCurrentPosition()
                + "-"
                + (downloadSaveStatus.getDownloadLength() + downloadSaveStatus.getStartPosition() - 1));
        Request request = HttpUtils.getRequest(
                downloadFile.getUrl(),
                downloadFile.getRequestMethod(),
                head,
                null,
                null);
        InputStream in = null;
        Response response = null;
        int total = 0;
        int len = 0;
        boolean isComplete = false;
        try {
            for (int i = 0; i < 3; i++) {// 重试3此
                try {
                    RandomAccessFile file = new RandomAccessFile(
                            downloadFile.getSavePath() + File.separator + downloadFile.getSaveName() + ".j",
                            "rw");
                    file.seek(downloadSaveStatus.getCurrentPosition());// 偏移一次

                    response = client.newCall(request).execute();
                    in = response.body().byteStream();
                    //Headers headers = response.headers();
                    byte[] bytes = new byte[1024];
                    while ((len = in.read(bytes)) != -1) {
                        file.write(bytes, 0, len);
                        downloadSaveStatus.setCurrentPosition(downloadSaveStatus.getCurrentPosition() + len);
                        total += len;
                        controller.currentDownloadSize += len;
                        if (controller.isPause) {
                            // 暂停
                            log.info("暂停当前任务，线程id：{}", Thread.currentThread().getId());
                            downloadSaveStatus.setStatus(JConstants.FILE_STATUS_PAUSE);
                            DownloadSaveStatusDao.update(downloadSaveStatus);
                            IoUtil.close(file);
                            IoUtil.close(in);
                            return;
                        } else if (controller.isDelete) {
                            //DownloadSaveStatusDao.delete(downloadSaveStatus);
                            IoUtil.close(file);
                            IoUtil.close(in);
                            return;
                        }
                        // 下载完成
                        if (total == downloadSaveStatus.getDownloadLength()) {
                            isComplete = true;
                            break;
                        }
                        if (downloadSaveStatus.getDownloadLength()-total<=1024){
                            bytes=new byte[downloadSaveStatus.getDownloadLength()-total];
                        }
                    }
                    isComplete = true;
                    log.info("thread - {} 下载完成，大小：{} byte", Thread.currentThread().getId(), total);
                    IoUtil.close(file);
                    break;
                } catch (Exception e) {
                    downloadSaveStatus.setRemarks(downloadSaveStatus.getRemarks() + "/n/n/n" + e.toString());
                    downloadSaveStatus.setRetryNumber(downloadSaveStatus.getRetryNumber() + 1);
                    DownloadSaveStatusDao.update(downloadSaveStatus);
                    if (e instanceof TimeoutException) {
                        System.out.println("超时异常！");
                    }
                    log.warn("下载异常！", e);
                    try {// 延迟一下
                        Thread.sleep(3333);
                    } catch (Exception s) {
                    }
                }
            }
        } catch (Exception e) {
            log.error("任务下载异常：", e);
        }
        if (isComplete) {
            downloadSaveStatus.setStatus(JConstants.FILE_STATUS_FINISH);
        } else {
            downloadSaveStatus.setStatus(JConstants.FILE_STATUS_NOT_FINISH);
        }
        DownloadSaveStatusDao.update(downloadSaveStatus);
    }

    public static void main(String[] args) throws Exception {
        OkHttpClient client = new OkHttpClient.Builder()
                .connectTimeout(20, TimeUnit.SECONDS) //连接超时
//            .readTimeout(READ_TIMEOUT, TimeUnit.SECONDS) //读取超时
//            .writeTimeout(WRITE_TIMEOUT, TimeUnit.SECONDS) //写超时
                .addInterceptor(new AddChrome95RequestHeadersInterceptor())
                .build();
        Map<String, String> head = new HashMap<>();
        head.put("Range", "bytes=1084100-1084104");
        Request request = HttpUtils.getRequest(
                "https://h97j.oss-cn-shanghai.aliyuncs.com/download/Visual%20Studio%202020_0121227758.exe",
                null,
                head,
                null,
                null);

        Response response = client.newCall(request).execute();
        InputStream in = response.body().byteStream();
        byte[] bytes = new byte[1024];
        int len = 0;
        int total = 0;
        while ((len = in.read(bytes)) != -1) {
            total += len;
        }
        System.out.println(total);
    }
}
